//
//  LVDatasourceHelper.m
//  Live
//
//  Created by RoyLei on 16/7/2.
//  Copyright © 2016年 Heller. All rights reserved.
//

#import "LVDatasourceHelper.h"
#import "LVConnectStatusInfoView.h"
#import "LVLoadingView.h"
#import "LVHUD.h"
#import "LKRequestLocalCodeHandler.h"
#import "MJRefreshFooter.h"
#import "MJRefreshHeader.h"
#import "BNDOfficeDocKit.h"

#define LKVIEWBOTTOM(view) CGRectGetMaxY(view.frame)
#define LKVIEWRIGHT(view)  CGRectGetMaxX(view.frame)
#define LKVIEWIDTH(view)   CGRectGetWidth(view.frame)
#define LKVIEHEIGHT(view)  CGRectGetHeight(view.frame)

@interface LVDatasourceHelper()

@property (nonatomic, strong) NSMutableSet *showIndexes;
@property (nonatomic, assign) NSTimeInterval lastReloadTime;

@end

@implementation LVDatasourceHelper

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.style = kStyleEmptyDefault;
        self.coverHeader = YES;
        self.loadOnce = NO;
        self.showLoading = YES;
        self.datas = [NSMutableArray new];
        self.numberOfPage = 20;
        self.delayLoadingInterval = 0.15;
    }
    return self;
}

#pragma mark - Setter

- (void)setCurrentScrollView:(UIScrollView *)currentScrollView
{
    if (_currentScrollView != currentScrollView) {
        _currentScrollView = currentScrollView;
        
        if (@available(iOS 11.0, *)) {
            _currentScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
        }
    }
}

#pragma mark - Getter

- (NSMutableSet *)showIndexes
{
    if (!_showIndexes) {
        _showIndexes = [NSMutableSet set];
    }
    
    return _showIndexes;
}

- (LVConnectStatusInfoView *)createStatusView:(StatusType)type errcode:(NSInteger)errcode inView:(UIView *)view
{
    UIScrollView *scrollView = nil;
    CGRect rect = CGRectZero;

    if([view isKindOfClass:[UITableView class]]
       &&
       [(UITableView *)view tableHeaderView] != nil
       &&
       !self.coverHeader)
    {
        UITableView *tableView = (UITableView *)view;
        rect = CGRectMake(0, LKVIEHEIGHT(tableView.tableHeaderView), LKVIEWIDTH(tableView), LKVIEHEIGHT(tableView) - LKVIEHEIGHT(tableView.tableHeaderView));
    }
    else
    {
        rect = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height);
    }
    
    if ([view isKindOfClass:[UIScrollView class]]) {
        scrollView = (UIScrollView *)view;
    }
    
    UIEdgeInsets originInset = scrollView.contentInset;
    
    // 这是因为设置mj_footer的时候contentInset的底部会增加一个mj_footer.height
    if(scrollView.mj_footer != nil) {
        originInset.bottom = scrollView.contentInset.bottom - scrollView.mj_footer.height;
    }
    
    rect.size.height -= (originInset.top + originInset.bottom);
    
    if (![self.statusInfoView isDescendantOfView:view]) {
        LVConnectStatusInfoView *statusInfoView = [[LVConnectStatusInfoView alloc] initWithFrame:rect];
        self.statusInfoView = statusInfoView;
    }
    
    BOOL needTapAction = NO;
    
    NSString *imageName = nil;
    NSString *desc = nil;
    
    
    if(type == kStatusViewTypeNetworkErr)
    {
        
        needTapAction = YES;
        imageName = @"bnd_qsy_wangluoyc";
        desc =  [LKRequestLocalCodeHandler errorDescriptionWithErrorCode:errcode];
        if(desc.length ==0) {
            desc = @"网络异常,点击重试~";
        }
    }
    else if(type == kStatusViewTypeEmpty)
    {
        imageName = @"officeDoc_qsy_zawuneirong";
        
        switch (self.style)
        {
            case kStyleEmptyNone:
                break;
            case kStyleEmptySearch:
                desc = @"暂时还没有数据哦~";
                break;
            case kStyleEmptyPeople:
                desc = @"无数据，稍后试试";
                break;
            case kStyleEmptyFans:
                desc = @"还没有粉丝，快去直播互动吧~";
                break;
            case kStyleEmptyFollow:
                desc = @"没有内容，快去撩新主播吧～";
                needTapAction = YES;
                break;
            case kStyleEmptyMyLive:
                desc = @"你还没有直播哦～";
                break;
            case kStyleEmptyOtherLive:
                desc = @"暂时还没有数据哦～";
                break;
            case kStyleEmptyContribution:
                desc = @"主播加把劲，快去撩土豪吧~";
                break;
            case kStyleEmptySend:
                desc = @"土豪你怎么还不出现~";
                break;
            case kStyleEmptyChat:
                desc = @"没人撩过？快去撩主播吧~";
                break;
            default:
                desc = @"暂无内容";
                needTapAction = YES;
                break;
        }
    }

  
    
    self.statusInfoView.infoImageView.image = BNDImageNamed(imageName);
    self.statusInfoView.infoLabel.text = desc;
    [view addSubview:self.statusInfoView];
    
    // 将没有消失的loading 置顶显示
    LVLoadingView *loadingView = nil;
    for(UIView *subView in view.subviews) {
        if ([subView isKindOfClass:[LVLoadingView class]]) {
            loadingView = (LVLoadingView *)subView;
            break;
        }
    }
    
    if (loadingView && !loadingView.hidden) {
        [view bringSubviewToFront:loadingView];
    }
    
    if (needTapAction) {
        WS(weakSelf)
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
        [[tap rac_gestureSignal] subscribeNext:^(id x) {
            [weakSelf.statusInfoView setUserInteractionEnabled:NO];
            [weakSelf.statusInfoView.infoLabel setText:@"加载中，请稍候~"];
            [weakSelf reload];
        }];
        [self.statusInfoView addGestureRecognizer:tap];
    }
    
    return self.statusInfoView;
}



- (void)endRefreshingWithNoMoreData
{
    if([self.currentScrollView respondsToSelector:@selector(mj_footer)] && [self.currentScrollView mj_footer] != nil) {
        [[self.currentScrollView mj_footer] endRefreshingWithNoMoreData];
    }
}

- (void)endFooterRefreshing
{
    if([self.currentScrollView respondsToSelector:@selector(mj_footer)] && [self.currentScrollView mj_footer] != nil && [[self.currentScrollView mj_footer] isRefreshing])
    {
        [[self.currentScrollView mj_footer] endRefreshing];
    }
}

- (void)endHeaderRefreshing
{
    if([self.currentScrollView respondsToSelector:@selector(mj_header)] && [self.currentScrollView mj_header] != nil && [[self.currentScrollView mj_header] isRefreshing])
    {
        [[self.currentScrollView mj_header] endRefreshing];
    }
}

- (void)resetNoMoreData
{
    if([self.currentScrollView respondsToSelector:@selector(mj_footer)] && [self.currentScrollView mj_footer] != nil)
    {
        [[self.currentScrollView mj_footer] resetNoMoreData];
    }
}

- (void)resetStatus
{
    self.currentScrollView.bounces = YES;
    self.currentScrollView.scrollEnabled = YES;
    
    if(nil != _hintView) {
        [_hintView removeFromSuperview];
        _hintView = nil;
    }
    
    if (nil != _statusInfoView) {
        [_statusInfoView removeFromSuperview];
        _statusInfoView = nil;
    }
}

#pragma mark - LVDatasourceHelperProtocol

- (void)reloadData
{
    
}

- (void)loadMore
{
    if (!self.isLoading) {
        self.isLoading = YES;
        _isReloading = NO;
        [self.currentScrollView.mj_header setHidden:YES];
    }
}

- (void)reload
{
    if (!self.isLoading) {
        _isReloading = YES;

        self.isLoading = YES;
        self.currentPage = kStartPage;
        [self.currentScrollView.mj_footer setHidden:YES];
        [_showIndexes removeAllObjects];
        
        _lastReloadTime = CFAbsoluteTimeGetCurrent();
        _endWatchRefeshList = NO;

         [_currentScrollView.mj_footer setHidden:YES];
        self.lastUpdateTime = [NSDate date];
    }
}

- (void)reloadNotPullView
{
    self.isLoading = YES;
    self.currentPage = kStartPage;
    [self.currentScrollView.mj_footer setHidden:YES];
    [_showIndexes removeAllObjects];
    
    _lastReloadTime = CFAbsoluteTimeGetCurrent();
    _endWatchRefeshList = NO;
    self.lastUpdateTime = [NSDate date];
}

- (void)reloadAndAutoPullView
{
    if (!_isLoading) {
        self.currentPage = kStartPage;
        [self.showIndexes removeAllObjects];
        [_currentScrollView.mj_header beginRefreshing];
        
        _lastReloadTime = CFAbsoluteTimeGetCurrent();
        _endWatchRefeshList = NO;
        self.lastUpdateTime = [NSDate date];
    }
}

- (void)finish:(NSArray *)data inView:(UIView *)view
{
    if(self.currentPage == kStartPage) // 从第一页请求数据则清空
    {
        [self.datas removeAllObjects];
        if(data && data.count > 0) {
            self.currentPage++;
            [self.datas addObjectsFromArray:data];
        }

        [self reloadData];
        [self resetNoMoreData];
        
        if (self.datas.count == 0) {
            self.hintView = [self createStatusView:kStatusViewTypeEmpty errcode:TLV_OK inView:view];
            self.currentScrollView.bounces = NO;
            self.currentScrollView.scrollEnabled = NO;
        }
        
    }else {
        if(data && data.count > 0) {
            self.currentPage++;
            [self.datas addObjectsFromArray:data];
            [self reloadData];
        }
    }
    
    if (self.datas.count > 0 && (data == nil || [data count] == 0)) {
        [self endRefreshingWithNoMoreData];
    }else if (self.datas.count == 0 && (data == nil || [data count] == 0)) {
        [self endFooterRefreshing];
    }
    
    self.isLoading = NO;
}

- (void)finish:(NSArray *)data errcode:(NSInteger)errcode inView:(UIView *)view
{
    [self cancelDelayLoading];
    
    [self.statusInfoView setUserInteractionEnabled:YES];
    [self.currentScrollView.mj_header setHidden:NO];
    [self.currentScrollView.mj_footer setHidden:NO];

    [self endHeaderRefreshing];
    [self endFooterRefreshing];
    
    [self resetStatus];

    if(errcode == TLV_OK)
    {
        [self finish:data inView:view];
    }
    //MARK: 处理网络失败
    else
    {
        if (!self.datas || self.datas.count == 0) { //之前已经请求到数据，则不再遮盖住数据页面
            
            self.hintView = [self createStatusView:kStatusViewTypeNetworkErr errcode:errcode inView:view];
            
            self.currentScrollView.bounces = NO;
            self.currentScrollView.scrollEnabled = NO;
        }
    }
    
    if(self.showLoading) {
        [LVLoadingView hideLoadingViewForView:view delay:0];
    }
    
    self.isLoading = NO;
}

- (void)delayLoading
{
    UIEdgeInsets contentInset = self.currentScrollView.contentInset;
    if (self.currentScrollView.mj_footer) {
        contentInset = self.currentScrollView.mj_footer.scrollViewOriginalInset;
    }
    CGRect frame = CGRectMake(0, 0, self.currentScrollView.width, self.currentScrollView.height - contentInset.top - contentInset.bottom);
    
    [LVLoadingView showLoadingViewAddedTo:self.currentScrollView frame:frame coverHeader:self.coverHeader];
    [LVLoadingView startAnimationTo:self.currentScrollView];
}

- (void)cancelDelayLoading
{
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(delayLoading) object:nil];
}

#pragma mark - UIScrollViewDelegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if(_scrollDelegate && [_scrollDelegate respondsToSelector:@selector(scrollViewDidScroll:)]) {
        [_scrollDelegate scrollViewDidScroll:scrollView];
    }
}

#pragma mark - Cell Display Animation

- (void)scaleAnimationCell:(UIView *)cell
{
    cell.layer.shadowColor = [[UIColor blackColor] CGColor];
    cell.layer.shadowOffset = CGSizeMake(10, 10);
    cell.layer.opacity = 0;
    cell.layer.transform = CATransform3DMakeScale(0.7, 0.7, 0.7);
    
    [UIView beginAnimations:@"scaleAnimationCell" context:NULL];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
    [UIView setAnimationDuration:0.4];
    cell.layer.shadowOffset = CGSizeMake(0, 0);
    cell.layer.opacity = 1;
    cell.layer.transform = CATransform3DIdentity;
    [UIView commitAnimations];
}

- (void)scaleSpringAnimationCell:(UIView *)cell
{
    cell.layer.shadowColor = [[UIColor blackColor] CGColor];
    cell.layer.shadowOffset = CGSizeMake(10, 10);
    cell.layer.opacity = 0;
    cell.layer.transform = CATransform3DMakeScale(0.7, 0.7, 0.7);
    
    [UIView beginAnimations:@"scaleAnimationCell" context:NULL];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
    [UIView setAnimationDuration:0.4];
    cell.layer.shadowOffset = CGSizeMake(0, 0);
    cell.layer.opacity = 1;
    [UIView commitAnimations];
    
    [UIView animateWithDuration:0.7 delay:0.0 usingSpringWithDamping:0.4f initialSpringVelocity:0.4 options:UIViewAnimationOptionCurveEaseIn|UIViewAnimationOptionAllowUserInteraction animations:^{
        cell.layer.transform = CATransform3DIdentity;
    } completion:^(BOOL finished) {
    }];
}

- (void)rotationAnimationCell:(UIView *)cell
{
    CGFloat rotationAngleDegrees = -30;
    CGFloat rotationAngleRadians = rotationAngleDegrees * (M_PI/ 180);
    CGPoint offsetPositioning = CGPointMake(-80, -80);
    
    CATransform3D transform = CATransform3DIdentity;
    transform = CATransform3DRotate(transform, rotationAngleRadians, 0.0,  0.0, 1.0);
    transform = CATransform3DTranslate(transform, offsetPositioning.x, offsetPositioning.y , 0.0);
    
    cell.layer.transform = transform;
    cell.layer.opacity = 0.0;
    
    [UIView beginAnimations:@"rotationCellAnima" context:NULL];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
    [UIView setAnimationDuration:0.4];
    cell.layer.opacity = 1;
    [UIView commitAnimations];
    
    [UIView animateWithDuration:0.7 delay:0.0 usingSpringWithDamping:0.6f initialSpringVelocity:0.2 options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionAllowUserInteraction animations:^{
        cell.layer.transform = CATransform3DIdentity;
    } completion:^(BOOL finished) {
    }];
}

- (void)moveInCell:(UIView *)cell
{
    cell.layer.shadowColor = [[UIColor blackColor]CGColor];
    cell.layer.shadowOffset = CGSizeMake(10, 10);
    cell.layer.opacity = 0;
    
    CGPoint point = cell.layer.position;
    point.y += 150;
    cell.layer.position = point;
    
    [UIView beginAnimations:@"moveInCell" context:NULL];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
    [UIView setAnimationDuration:0.4];
    cell.layer.opacity = 1;
    cell.layer.shadowOffset = CGSizeMake(0, 0);
    [UIView commitAnimations];
    
    point.y -= 150;
    [UIView animateWithDuration:0.5 delay:0.2 usingSpringWithDamping:15.0f initialSpringVelocity:0.5 options:UIViewAnimationOptionCurveEaseIn|UIViewAnimationOptionAllowUserInteraction animations:^{
        cell.layer.position = point;
    } completion:^(BOOL finished) {
    }];
}

- (void)rotationFromBottomAnimationForCell:(UIView *)cell
{
    CATransform3D rotation;
    rotation = CATransform3DMakeRotation( (90.0*M_PI)/180, 0.0, 0.7, 0.4);
    rotation.m34 = 1.0/ -600;

    cell.layer.shadowColor = [[UIColor blackColor]CGColor];
    cell.layer.shadowOffset = CGSizeMake(10, 10);
    cell.alpha = 0;

    cell.layer.transform = rotation;
//    cell.layer.anchorPoint = CGPointMake(0, 0.5);

    [UIView beginAnimations:@"rotationFromBottom" context:NULL];
    [UIView setAnimationDuration:0.4];
    cell.layer.transform = CATransform3DIdentity;
    cell.alpha = 1;
    cell.layer.shadowOffset = CGSizeMake(0, 0);
    [UIView commitAnimations];
}

#define DEGREES_TO_RADIANS(d) (d * M_PI / 180)

- (void)animationForIndexPath:(NSIndexPath *)indexPath cell:(UIView *)cell {
    NSInteger row = indexPath.row;
    float radians = (120 + row*30)%360;
    radians = 20;
    CALayer *layer = cell.layer;
    // Rotation Animation
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    animation.fromValue =@DEGREES_TO_RADIANS(radians);
    animation.toValue = @DEGREES_TO_RADIANS(0);
    // Opacity Animation;
    CABasicAnimation *fadeAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    fadeAnimation.fromValue = @0.1f;
    fadeAnimation.toValue = @1.f;
    // Translation Animation
    CABasicAnimation *translationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
    ;
    translationAnimation.fromValue = @(-300.f * ((indexPath.row%2 == 0) ? -1: 1));
    translationAnimation.toValue = @0.f;
    CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
    animationGroup.duration = 0.4f;
    animationGroup.animations = @[animation,fadeAnimation,translationAnimation];
    animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    [layer addAnimation:animationGroup forKey:@"spinAnimation"];
}

@end
